def type_to_s(type)
  if type == Integer
    'Number'
  elsif type == Object
    'Id'
  else
    type.to_s
  end
end

def type(field, klass)
  type =
      if klass.fields.include?(field)
        klass.fields[field].type
      elsif klass.relations.include?(field)
        klass.relations[field].klass
      else
        raise "Unexpected field desc of #{klass}: #{field}"
      end
  type_to_s(type)
end

def type_as_param(field, klass)
  if klass.relations.include?(field)
    field = klass.relations[field].key
  end
  type = type(field, klass)
  [field, type]
end

def define_return_resource(klass, out)
  out.puts '#**'
  out.puts "# @apiDefine Return#{klass}"
  out.puts '#'
  desc_options = klass.instance_eval { @desc_options }
  desc_options.each do |field, desc|
    type = type(field, klass)
    out.puts "# @apiSuccess {#{type}} #{field} #{desc}"
  end
  out.puts '#*'
end

def define_return_resource_array(klass, out)
  out.puts '#**'
  out.puts "# @apiDefine Return#{klass}Array"
  out.puts '#'
  desc = klass.instance_eval { @desc }
  out.puts "# @apiSuccess {#{klass}[]} _ #{desc}列表"
  desc_options = klass.instance_eval { @desc_options }
  desc_options.each do |field, desc|
    type = type(field, klass)
    out.puts "# @apiSuccess {#{type}} _.#{field} #{desc}"
  end
  out.puts '#*'
end

def define_resource_params(klass, out)
  out.puts '#**'
  out.puts "# @apiDefine #{klass}Params"
  out.puts '#'
  desc_options = klass.instance_eval { @desc_options }
  desc_options.each do |field, desc|
    field, type = type_as_param(field, klass)
    desc = "#{desc} id" if type == 'Id'
    out.puts "# @apiParam {#{type}} #{field} #{desc}"
  end
  out.puts '#*'
end

def generate_resource_definitions
  path_prefix = "#{Rails.root}/app/controllers/.resource_definitions"
  FileUtils.rm_rf(path_prefix) if Dir.exist?(path_prefix)
  Dir.mkdir(path_prefix)
  Dir.foreach("#{Rails.root}/app/models") do |filename|
    next if filename.start_with?('.') || !filename.end_with?('.rb')

    model_name = filename.split('.rb')[0]
    klass = model_name.camelize.constantize
    path = "#{path_prefix}/#{model_name}.rb"
    File.open(path, 'w+') do |file|
      define_return_resource(klass, file)
      file.puts
      define_return_resource_array(klass, file)
      file.puts
      define_resource_params(klass, file)
      file.puts
    end
  end
end

task :apidoc => :environment do
  generate_resource_definitions
  appname = Rails.application.class.parent_name.underscore
  `apidoc -i #{Rails.root}/app/controllers -o #{Rails.root}/../#{appname}_apidoc`
end
